package com.sssre.lttcloud.codegen.service.impl;

import com.baomidou.mybatisplus.annotation.TableField;
import com.sssre.lttcloud.codegen.entity.ColumnInfo;
import com.sssre.lttcloud.codegen.entity.TableInfo;
import com.sssre.lttcloud.codegen.mapper.ColumnInfoMapper;
import com.sssre.lttcloud.codegen.mapper.TableInfoMapper;
import com.sssre.lttcloud.codegen.service.CodeGenService;
import com.sssre.lttcloud.codegen.utils.JdbcUtils;
import com.sssre.lttcloud.common.result.Result;
import com.sssre.lttcloud.common.result.ResultCode;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.io.StringWriter;
import java.sql.SQLException;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 代码生成服务实现类
 */
@Service
public class CodeGenServiceImpl implements CodeGenService {

    @Autowired
    private ColumnInfoMapper columnInfoMapper;

    @Autowired
    private TableInfoMapper tableInfoMapper;

    @Autowired
    private Configuration freemarkerConfig;

    @Autowired
    private JdbcUtils jdbcUtils;

    @Override
    public Result<List<TableInfo>> getTableList() {
        try {
            List<Map<String, Object>> tables = jdbcUtils.getTableList();
            List<TableInfo> tableInfoList = new ArrayList<>();

            for (Map<String, Object> table : tables) {
                TableInfo tableInfo = new TableInfo();
                tableInfo.setTableName((String) table.get("TABLE_NAME"));
                tableInfo.setTableComment((String) table.get("TABLE_COMMENT"));
                tableInfo.setClassName(convertToCamelCase(tableInfo.getTableName()));
                tableInfo.setPackageName("com.sssre.lttcloud");
                tableInfo.setAuthor("System");
                tableInfo.setIsGenerate(false);
                tableInfoList.add(tableInfo);
            }
            
            return Result.success(tableInfoList);
        } catch (SQLException e) {
            return Result.failed(ResultCode.SYSTEM_ERROR, "获取表列表失败: " + e.getMessage());
        }
    }

    @Override
    public Result<List<TableInfo>> getTableColumns(String tableName) {
        try {
            List<Map<String, Object>> columns = jdbcUtils.getTableColumns(tableName);
            List<ColumnInfo> columnInfoList = new ArrayList<>();
            
            for (Map<String, Object> column : columns) {
                ColumnInfo columnInfo = new ColumnInfo();
                columnInfo.setTableName(tableName);
                columnInfo.setColumnName((String) column.get("COLUMN_NAME"));
                columnInfo.setColumnType((String) column.get("DATA_TYPE"));
                columnInfo.setColumnComment((String) column.get("COLUMN_COMMENT"));
                columnInfo.setIsPrimaryKey("PRI".equals(column.get("COLUMN_KEY")));
                columnInfo.setIsRequired("NO".equals(column.get("IS_NULLABLE")));
                columnInfo.setIsQuery(false);
                columnInfo.setIsList(true);
                columnInfo.setIsEdit(true);
                columnInfo.setQueryType("eq");
                
                Object length = column.get("CHARACTER_MAXIMUM_LENGTH");
                if (length != null) {
                    columnInfo.setColumnLength(Integer.valueOf(length.toString()));
                }
                
                columnInfo.setDefaultValue((String) column.get("COLUMN_DEFAULT"));
                columnInfoList.add(columnInfo);
            }
            
            TableInfo tableInfo = new TableInfo();
            tableInfo.setTableName(tableName);
            tableInfo.setColumns(columnInfoList);
            
            return Result.success(Collections.singletonList(tableInfo));
        } catch (SQLException e) {
            return Result.failed(ResultCode.SYSTEM_ERROR, "获取表字段失败: " + e.getMessage());
        }
    }

    @Override
    public Result<String> generateCode(TableInfo tableInfo) {
        try {
            // 生成各种代码文件
            Map<String, String> codeFiles = new HashMap<>();
            
            // 生成Entity
            codeFiles.put("Entity.java", generateEntity(tableInfo));
            
            // 生成Repository
            codeFiles.put("Repository.java", generateRepository(tableInfo));
            
            // 生成Service
            codeFiles.put("Service.java", generateService(tableInfo));
            
            // 生成ServiceImpl
            codeFiles.put("ServiceImpl.java", generateServiceImpl(tableInfo));
            
            // 生成Controller
            codeFiles.put("Controller.java", generateController(tableInfo));
            
            // 生成DTO
            codeFiles.put("DTO.java", generateDTO(tableInfo));
            
            return Result.success("代码生成成功");
        } catch (Exception e) {
            return Result.failed(ResultCode.SYSTEM_ERROR, "代码生成失败: " + e.getMessage());
        }
    }

    @Override
    public Result<Object> previewCode(TableInfo tableInfo) {
        try {
            Map<String, Object> preview = new HashMap<>();
            preview.put("entity", generateEntity(tableInfo));
            preview.put("repository", generateRepository(tableInfo));
            preview.put("service", generateService(tableInfo));
            preview.put("serviceImpl", generateServiceImpl(tableInfo));
            preview.put("controller", generateController(tableInfo));
            preview.put("dto", generateDTO(tableInfo));
            
            return Result.success(preview);
        } catch (Exception e) {
            return Result.failed(ResultCode.SYSTEM_ERROR, "代码预览失败: " + e.getMessage());
        }
    }

    @Override
    public Result<byte[]> downloadCode(TableInfo tableInfo) {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ZipOutputStream zos = new ZipOutputStream(baos);
            
            // 添加各种代码文件到zip
            addToZip(zos, "Entity.java", generateEntity(tableInfo));
            addToZip(zos, "Repository.java", generateRepository(tableInfo));
            addToZip(zos, "Service.java", generateService(tableInfo));
            addToZip(zos, "ServiceImpl.java", generateServiceImpl(tableInfo));
            addToZip(zos, "Controller.java", generateController(tableInfo));
            addToZip(zos, "DTO.java", generateDTO(tableInfo));
            
            zos.close();
            return Result.success(baos.toByteArray());
        } catch (Exception e) {
            return Result.failed(ResultCode.SYSTEM_ERROR, "代码下载失败: " + e.getMessage());
        }
    }

    // 私有方法
    private String convertToCamelCase(String tableName) {
        String[] parts = tableName.split("_");
        StringBuilder result = new StringBuilder();
        for (String part : parts) {
            if (part.length() > 0) {
                result.append(Character.toUpperCase(part.charAt(0)))
                      .append(part.substring(1).toLowerCase());
            }
        }
        return result.toString();
    }

    private void addToZip(ZipOutputStream zos, String fileName, String content) throws Exception {
        ZipEntry entry = new ZipEntry(fileName);
        zos.putNextEntry(entry);
        zos.write(content.getBytes());
        zos.closeEntry();
    }

    private String generateEntity(TableInfo tableInfo) throws Exception {
        Map<String, Object> model = new HashMap<>();
        model.put("tableInfo", tableInfo);
        model.put("className", tableInfo.getClassName());
        model.put("packageName", tableInfo.getPackageName());
        
        Template template = freemarkerConfig.getTemplate("entity.ftl");
        StringWriter writer = new StringWriter();
        template.process(model, writer);
        return writer.toString();
    }

    private String generateRepository(TableInfo tableInfo) throws Exception {
        Map<String, Object> model = new HashMap<>();
        model.put("tableInfo", tableInfo);
        model.put("className", tableInfo.getClassName());
        model.put("packageName", tableInfo.getPackageName());
        
        Template template = freemarkerConfig.getTemplate("repository.ftl");
        StringWriter writer = new StringWriter();
        template.process(model, writer);
        return writer.toString();
    }

    private String generateService(TableInfo tableInfo) throws Exception {
        Map<String, Object> model = new HashMap<>();
        model.put("tableInfo", tableInfo);
        model.put("className", tableInfo.getClassName());
        model.put("packageName", tableInfo.getPackageName());
        
        Template template = freemarkerConfig.getTemplate("service.ftl");
        StringWriter writer = new StringWriter();
        template.process(model, writer);
        return writer.toString();
    }

    private String generateServiceImpl(TableInfo tableInfo) throws Exception {
        Map<String, Object> model = new HashMap<>();
        model.put("tableInfo", tableInfo);
        model.put("className", tableInfo.getClassName());
        model.put("packageName", tableInfo.getPackageName());
        
        Template template = freemarkerConfig.getTemplate("serviceImpl.ftl");
        StringWriter writer = new StringWriter();
        template.process(model, writer);
        return writer.toString();
    }

    private String generateController(TableInfo tableInfo) throws Exception {
        Map<String, Object> model = new HashMap<>();
        model.put("tableInfo", tableInfo);
        model.put("className", tableInfo.getClassName());
        model.put("packageName", tableInfo.getPackageName());
        
        Template template = freemarkerConfig.getTemplate("controller.ftl");
        StringWriter writer = new StringWriter();
        template.process(model, writer);
        return writer.toString();
    }

    private String generateDTO(TableInfo tableInfo) throws Exception {
        Map<String, Object> model = new HashMap<>();
        model.put("tableInfo", tableInfo);
        model.put("className", tableInfo.getClassName());
        model.put("packageName", tableInfo.getPackageName());
        
        Template template = freemarkerConfig.getTemplate("dto.ftl");
        StringWriter writer = new StringWriter();
        template.process(model, writer);
        return writer.toString();
    }
} 